package bubbleindex;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

/**
 *
 * @author t
 */
public class URLS {
    private String dataName;
    private String url;
    private String dataType;
    private String source;
    private Path path;
    private final int startYear = 1900;
    private Date today;
    private final DateFormat df = new SimpleDateFormat("yyyy");
    private boolean INDEX = false;
    private String yahooSymbol;
    private String QuandlDataset;
    private String QuandlName;
    private int QuandlColumn;
    private boolean specialSymbol = false;
    
    /**
     * 
     */
    public void setToday() {
        this.today = new Date();
    }
    
    /**
     * 
     * @param dataName 
     */
    public void setDataName (String dataName) {
        this.dataName = dataName;
        final String name = this.dataName;
        BubbleIndex.displayOutput("GET: " + name, false);
    }
    
    /**
     * 
     */
    public void setYahooUrl() {
        if (this.INDEX) {
            this.yahooSymbol = "%5E";
        }
        else {
            this.yahooSymbol = "";
        }
        
        this.url = "http://ichart.yahoo.com/table.csv?s=" + this.yahooSymbol + this.dataName 
                + "&a=0&b=1&c=" + this.startYear + "&d=11&e=31&f=" 
                + getYear() + "&g=d&ignore=.csv";
    }    
    
    /**
     * 
     */
    public void setFEDUrl() {
        this.url = "http://research.stlouisfed.org/fred2/series/" + this.dataName 
                + "/downloaddata/" + this.dataName + ".csv";
    }
    
    /**
     * 
     * @param dataset
     * @param name 
     */
    public void setQuandlUrl(String dataset, String name) {
        this.QuandlDataset = dataset;
        this.QuandlName = name;
        this.url = "http://www.quandl.com/api/v1/datasets/" + this.QuandlDataset +
                "/" + this.QuandlName + ".csv?sort_order=asc";
    }
    
    /**
     * 
     * @param Column 
     */
    public void setQuandlColumn(int Column) {
        this.QuandlColumn = Column;
    }
    
    /**
     * 
     */
    public void isSpecial() {
        this.specialSymbol = true;
    }
    
    /**
     * 
     * @param dataType 
     */
    public void setDataType(String dataType) {
        this.INDEX = this.specialSymbol;
        this.dataType = dataType;
    }

    /**
     * 
     * @param source 
     */
    public void setSource(String source) {
        this.source = source;
    }
    
    /**
     * 
     * @throws UnsupportedEncodingException 
     */
    public void setPath () throws UnsupportedEncodingException {
        this.path = FileSystems.getDefault().getPath(Indices.getFilePath() + this.dataName + "raw.csv");
        final Path pathstring = this.path;
        BubbleIndex.displayOutput("Path: " + pathstring + " ...", false);
    }
    
    /**
     * 
     * @return 
     */
    public String getYear() {
        setToday();
        String s = df.format(this.today);
        return s;
    }
    
    /**
     * 
     * @return 
     */
    public String getDataName () {
        return this.dataName;
    }
    
    /**
     * 
     * @return 
     */
    public String getUrl () {
        return this.url;
    }   
    
    /**
     * 
     * @return 
     */
    public Path getPath () {
        return this.path;
    }
    
    /**
     * 
     * @return 
     */
    public String getDataType () {
        return this.dataType;
    }
    
    /**
     * 
     * @return 
     */
    public String getSource () {
        return this.source;
    }
    
    /**
     * 
     * @throws FileNotFoundException
     * @throws IOException 
     */
    public void readURL_file(ByteArrayOutputStream outputstream) throws FileNotFoundException, IOException {
        final URL url1 = new URL(this.url);
        byte[] ba1 = new byte[1024];
        int baLength;
        //FileOutputStream fos1 = new FileOutputStream(Indices.getFilePath() + this.dataName + "raw.csv");
        try {
            //Create connection
            BubbleIndex.displayOutput("Connecting to " + url1.toString() + " ...", false);         
          
            URLConnection urlConn = url1.openConnection();

            try {
                BubbleIndex.displayOutput("Downloading the CSV ...", false);                        
                 
                // Read the CSV from the URL and save to a local file
                InputStream is1 = url1.openStream();
                while ((baLength = is1.read(ba1)) != -1) {
                    outputstream.write(ba1, 0, baLength);
                }
                outputstream.flush();
                //outputstream.close();
                is1.close();

            } catch (IOException e) {
                updateData.errors++;
                System.out.println("IO Exception. Failed while reading bytes from " +
                    url1.toExternalForm() + " : " + e.getMessage() + " Code 023.");
                final Exception e2 = e;
                BubbleIndex.displayOutput("Failed while reading bytes from " + 
                                url1.toExternalForm() + ": " + e2.getMessage(), false);                  
            }
              
        } catch (NullPointerException npe) {
            System.out.println("Null Pointer Exception. Code 024.");
            BubbleIndex.displayOutput("Invalid URL.", false);       
        }         
    }

    /**
     * 
     * @param outputstream
     * @throws FileNotFoundException
     * @throws IOException 
     */
    public void cleanData(ByteArrayOutputStream outputstream) throws FileNotFoundException, IOException {
        boolean YAHOO = false;
        boolean QUANDL = false;
        
        if (this.source.matches("Yahoo")) {
            YAHOO = true;
        }
        else if (this.source.matches("QUANDL")) {
            QUANDL = true;
        }
        
        Charset charset = Charset.forName("UTF-8");
        List<String> dateData = new ArrayList();
        List<String> priceData = new ArrayList();
        
        try {
            //BufferedReader reader = Files.newBufferedReader(this.path, charset);
            BufferedReader reader = new BufferedReader(new StringReader(outputstream.toString()));
            //Ignore header is True for Yahoo, FED, and QUANDL
            String line = reader.readLine();

            while ((line = reader.readLine()) != null) {
                //fileData.add(line);
                String[] splits = line.split(",");
                if (YAHOO) {
                    dateData.add(splits[0]);
                    priceData.add(splits[6]);
                }
                else if (QUANDL) {
                    dateData.add(splits[0]);
                    priceData.add(splits[this.QuandlColumn-1]);
                }
                else {
                    if (!splits[1].matches(".")) {
                        dateData.add(splits[0]);
                        priceData.add(splits[1]);
                    }
                }
            }
            
            if (YAHOO) {
            //Reverse Yahoo Data
                Collections.reverse(dateData);
                Collections.reverse(priceData);
            }
            //write data
                        
        } catch (IOException x) {
            System.out.println("IO Exception. Code 025.");
            BubbleIndex.displayOutput("Failed to process CSV file.", false);       
        }
        
        List<String> oldpriceData = new ArrayList();
        List<String> olddateData = new ArrayList();
                    
        Path filepath = FileSystems.getDefault().getPath(Indices.getFilePath() + 
            "ProgramData" + Indices.filePathSymbol + this.dataType +
            Indices.filePathSymbol + this.dataName + Indices.filePathSymbol + 
            this.dataName + "dailydata.csv");
        
        //if dailydata file already exists for certain countries, delete them
        String[] badCountries = {"HongKong", "Germany", "UnitedKingdom", "India", "Brazil",
            "China", "Japan", "Australia", "Argentina", "SouthKorea", "Israel",
            "Singapore", "Italy", "Mexico", "Indonesia", "France", "Canada",
            "Taiwan", "Austria", "Denmark", "Netherlands", "NewZealand", "Norway",
            "Spain", "Sweden", "Switzerland", "Russia", "Dubai", "Greece", "Baltic",
            "Peru", "Venezuela", "Chile"};

        boolean matchBadCountry = false;
        for (String badCountry : badCountries) {
            if (this.dataType.matches(badCountry) && Files.exists(filepath)) {
                matchBadCountry = true;
            }
        }
        
        if (matchBadCountry) {
            Files.delete(filepath);
        }

        if (Files.exists(filepath)) {
                
            BufferedReader reader = Files.newBufferedReader(filepath, charset);

            //No Header
            String line; //= reader.readLine();
            
            //All daily data is tab separated .tsv file really incorrect to name .csv
            while ((line = reader.readLine()) != null) {
                String[] splits = line.split("\t");
                olddateData.add(splits[0]);
                oldpriceData.add(splits[1]);
            }
            
            //find where dates match
            final String oldDateDataLastString = olddateData.get(olddateData.size() - 1);
            int match = 0;
            for (int i = 0; i < dateData.size(); i++) {
                if (oldDateDataLastString.matches(dateData.get(i))) {
                    match = i;
                }
            }
        
            File dailydata = new File(Indices.getFilePath() + "ProgramData" +
                    Indices.filePathSymbol + this.dataType + Indices.filePathSymbol + 
                    this.dataName + Indices.filePathSymbol + this.dataName + 
                    "dailydata.csv");
        
            dailydata.createNewFile();
            FileWriter writer = new FileWriter(dailydata);
        
            for (int i = 0; i < olddateData.size(); i++) {
                writer.write(olddateData.get(i) + "\t" + oldpriceData.get(i) + "\n");
            }
        
            for (int i = match + 1; i < dateData.size(); i++) {
                writer.write(dateData.get(i) + "\t" + priceData.get(i) + "\n");
            }
        
            writer.flush();
            writer.close();
            
        } else {
            
            try {
                File dailydata = new File(Indices.getFilePath() + "ProgramData" + 
                        Indices.filePathSymbol + this.dataType + Indices.filePathSymbol + 
                        this.dataName + Indices.filePathSymbol + this.dataName + "dailydata.csv");

                dailydata.createNewFile();
                FileWriter writer = new FileWriter(dailydata);
                for (int i = 0; i < dateData.size(); i++) {
                    writer.write(dateData.get(i) + "\t" + priceData.get(i) + "\n");
                }
                writer.flush();
                writer.close();
                
            } catch (IOException th) {
                final String name = this.dataName;
                System.out.println("IO Exception: " + name + " Code 026.");
                BubbleIndex.displayOutput("Failed to create daily data: " + name, false);                   
            }
        }    
    }       
}